package is.model.dao;

import is.interfaces.Bean;
import is.interfaces.Dao;
import is.model.DataSource;
import is.model.exceptions.ObjectNotFoundException;
import java.sql.*;
import java.util.LinkedList;
import java.util.List;

/**
 *
 * @author aspr0
 */
public abstract class AbstractDao<Datatype extends Bean> implements Dao<Datatype>
{
    protected Connection connection;
    protected Datatype initialBean;

    public AbstractDao()
    {
        this.connection = DataSource.getConnection();
    }

    @Override
    public void setInitialBean(Datatype initialBean)
    {
        this.initialBean = initialBean;
    }

    @Override
    public Integer count() throws SQLException
    {
        String query = "select count(*) count from %s";
        query = String.format(query, initialBean.getTableName());
        PreparedStatement statement = connection.prepareStatement(query);
        statement.execute();
        ResultSet resultSet = statement.getResultSet();
        resultSet.next();
        Integer count = resultSet.getInt("count");
        resultSet.close();
        return count;
    }

    @Override
    public Integer delete() throws SQLException
    {
        String query = "delete from %s where id = ? limit 1";
        query = String.format(query, initialBean.getTableName());
        PreparedStatement statement = connection.prepareStatement(query);
        statement.setInt(1, initialBean.getId());
        statement.execute();
        return statement.getUpdateCount();
    }

    @Override
    public void objectExists() throws SQLException, ObjectNotFoundException
    {
        String query = "select count(*) count from %s where id = ?";
        query = String.format(query, initialBean.getTableName());
        PreparedStatement statement = connection.prepareStatement(query);
        statement.setInt(1, initialBean.getId());
        statement.execute();
        ResultSet resultSet = statement.getResultSet();
        resultSet.next();
        Boolean objectExists;
        if (resultSet.getInt("count") < 1)
        {
            objectExists = false;
        }
        else
        {
            objectExists = true;
        }
        resultSet.close();
        if (!objectExists)
        {
            throw new ObjectNotFoundException();
        }
    }

    @Override
    public Datatype retrieve() throws SQLException
    {
        String query = "select * from %s where id = ? limit 1";
        query = String.format(query, initialBean.getTableName());
        PreparedStatement statement = connection.prepareStatement(query);
        statement.setInt(1, initialBean.getId());
        statement.execute();

        ResultSet resultSet = statement.getResultSet();
        Datatype returnBean = (Datatype) initialBean.clone();
        if (resultSet.next())
        {
            returnBean.processResultSet(resultSet);
        }
        resultSet.close();
        return returnBean;
    }

    @Override
    public List<Datatype> retrieveMultiple(Integer offset, Integer limit, Integer orderByIndex) throws SQLException
    {
        String query = "select * from %s order by %s limit %s,%s";
        String orderByString = (orderByIndex >= 0) ? initialBean.getFields()[orderByIndex] : "id";
        query = String.format(query, initialBean.getTableName(), orderByString, offset, limit);
        PreparedStatement statement = connection.prepareStatement(query);
        statement.execute();
        ResultSet resultSet = statement.getResultSet();
        List<Datatype> beans = new LinkedList<Datatype>();
        while (resultSet.next())
        {
            Datatype listBean = (Datatype) initialBean.clone();
            listBean.processResultSet(resultSet);
            beans.add(listBean);
        }
        return beans;
    }

    protected String genQmarksBycomma(Bean bean)
    {
        String[] fields = bean.getFields();
        String[] values = bean.getValues();

        String queryCanvas = "(%s) values (%s)";
        String delimiter = ", ";
        String qmark = "?";

        String fieldsString = "";
        String valuesString = "";

        Integer toStringCount = 0;

        for (int partNum = 0; partNum < fields.length; partNum++)
        {
            if (!values[partNum].isEmpty())
            {
                toStringCount++;

                fieldsString += (toStringCount == 1) ? fields[partNum] : delimiter + fields[partNum];

                valuesString += (toStringCount == 1) ? qmark : delimiter + qmark;
            }
        }

        return String.format(queryCanvas, fieldsString, valuesString);
    }

    protected String genQmarksByeqsign(Bean bean)
    {
        String[] fields = bean.getFields();
        String[] values = bean.getValues();

        String query = "";
        String equalSign = " = ";
        String delimiter = ", ";
        String defaultString = "default";
        String qmark = "?";
        String part;

        for (int partNum = 0; partNum < fields.length; partNum++)
        {
            if (values[partNum].isEmpty())
            {
                part = fields[partNum] + equalSign + defaultString;
            }
            else
            {
                part = fields[partNum] + equalSign + qmark;
            }

            query += (partNum < fields.length - 1) ? part + delimiter : part;
        }

        return query;
    }
}
